﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Linq;
using Datos;

namespace Consulta
{
    public class Consultas  : IConsultas
    {
        #region Variables
        
        private static Consultas instancia = null;
        private DataClassesDataContext bd;

        #endregion

        #region Constructores

        private Consultas()
        {
            bd = new DataClassesDataContext();
        }

        public static Consultas getInstancia()
        {
            if (instancia == null)
                instancia = new Consultas();
            return Instancia;
        }
 

        #endregion

        #region Properties

        public static Consultas Instancia
        {
            get
            {
                if (instancia == null)
                {
                    instancia = new Consultas();
                }
                return Consultas.instancia;
            }
        }

        #endregion

        #region Metodos para Categoria

        public int agregarCategoria(string nombre, string descripcion, char estado)
        {
            Categoria Cat = new Categoria();
            Cat.nombre = nombre;
            Cat.descripcion = descripcion;
            Cat.estado = estado;
            bd.Categoria.InsertOnSubmit(Cat);
            bd.SubmitChanges();
            return Cat.idCategoria;
        }

        public void modificarCategoria(int idCategoria, string nombre, string descripcion, char est)
        {
            try
            {
                Categoria cat = (from q in bd.Categoria
                            where q.idCategoria == idCategoria
                            select q).Single();
                                
                    cat.nombre = nombre;
                    cat.descripcion = descripcion;
                    cat.estado = est;                
                bd.SubmitChanges();
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        // No existe el eliminar, se hace en modificar con estado = N

        public List<string[]> traerCategorias(bool soloactivos)
        {
            try
            {
                IQueryable query; 
                List<string[]> list = new List<string[]>();
                if (soloactivos)
                {
                    query = from c in bd.Categoria
                                where c.estado == 'S'
                                select c;
                }
                else
                {
                    query = from c in bd.Categoria select c;
                }

                foreach (Categoria cat in query)
                {
                    string[] datos = new string[4];
                    datos[0] = cat.idCategoria.ToString();
                    datos[1] = cat.nombre;
                    datos[2] = cat.descripcion;
                    datos[3] = cat.estado.ToString();
                    list.Add(datos);
                }
                return list;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        #endregion

        #region Metodos para Cliente

        public int agregarCliente(string nombre, string apellido, string tel)
        {
            try
            {

                Cliente Cli = new Cliente();
                //Cli.idCliente = idCliente;
                Cli.nombre = nombre;
                Cli.apellido = apellido;
                Cli.telefono = tel;
                bd.Cliente.InsertOnSubmit(Cli);
                bd.SubmitChanges();
                return Cli.idCliente;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public void modificarCliente(int idCliente, string nombre, string apellido, string tel)
        {
            try
            {
                Cliente cli = (from c in bd.Cliente
                               where c.idCliente == idCliente
                               select c).Single();
                cli.nombre = nombre;
                cli.apellido = apellido;
                cli.telefono = tel;
                bd.SubmitChanges();

            }
            catch (Exception e)
            {
                throw e;
            }
            
        }
        /*
        public void EliminarCliente(int idCliente)
        {
            bool ok = true;
            try
            {
                var query = (from c in bd.Cliente
                             where c.idCliente == idCliente
                             select c).Single();
            }
            catch (Exception)
            {
                ok = false;
            }
            if (!ok)
            {
                Cliente cli = (from c in bd.Cliente
                               where c.idCliente == idCliente
                               select c).Single();
                bd.Cliente.DeleteOnSubmit(cli);
                bd.SubmitChanges();
            }
        }*/

        public string[] traerCliente(int idCliente)
        {
            string[] lst = new string[4];
            try
            {
                var cli = (from c in bd.Cliente
                               where c.idCliente == idCliente
                               select c).Single();
                
                
                lst[0] = cli.idCliente.ToString();
                lst[1] = cli.nombre;
                lst[2] = cli.apellido;
                lst[3] = cli.telefono;
                return lst;
            }
            catch (Exception e)
            {
                throw e;
            }
                
        }

        public List<string[]> traerClientes()
        {
            try
            {
                List<string[]> list = new List<string[]>();
                    var query = from c in bd.Cliente
                                select c;
               

                foreach (Cliente cli in query)
                {
                    string[] datos = new string[4];
                    datos[0] = cli.idCliente.ToString();
                    datos[1] = cli.nombre;
                    datos[2] = cli.apellido;
                    datos[3] = cli.telefono;
                    list.Add(datos);
                }
                return list;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #endregion

        #region Metodos para Comodidades

        public int agregarComodidad(string nombre, string descripcion, float costoExtra, char estado)
        {
            /*int resp = 1;
            string consulta = "select count(*) from HotelORT.dbo.Comodidad";
            IEnumerable<int> query = bd.ExecuteQuery<int>(consulta);
            foreach (int i in query)
            {
                resp = i + 1;
            }
             */
            try
            {
                Comodidad Com = new Comodidad();
                Com.costoExtra = costoExtra;
                Com.nombre = nombre;
                Com.estado = estado;
                Com.descripcion = descripcion;
                bd.Comodidad.InsertOnSubmit(Com);
                bd.SubmitChanges();
                return Com.idComodidad;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void modificarComodidad(int idComodidad, string nom, string desc, float costoExtra, char estado)
        {
            try
            {

                string consulta = "select * from HotelORT.dbo.Comodidad c where c.idComodidad = " + idComodidad;
                IEnumerable<Comodidad> query = bd.ExecuteQuery<Comodidad>(consulta);
                foreach (Comodidad com in query)
                {
                    com.nombre = nom;
                    com.estado = estado;
                    com.costoExtra = costoExtra;
                    com.descripcion = desc;
                }
                bd.SubmitChanges();

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        // No hay baja, solo se cambia el estado

        public List<string[]> traerComodidades(bool soloactivos)
        {
            try
            {
                List<string[]> list = new List<string[]>();
                IQueryable query;
                if (soloactivos)
                {
                    query = from c in bd.Comodidad
                            where c.estado == 'S'
                                select c;
                }
                else
                {
                    query = from c in bd.Comodidad
                                select c;
                }
                foreach (Comodidad com in query)
                {
                    string[] datos = new string[5];
                    datos[0] = com.idComodidad.ToString();
                    datos[1] = com.nombre;
                    datos[2] = com.descripcion;
                    datos[3] = com.costoExtra.ToString();
                    datos[4] = com.estado.ToString();
                    list.Add(datos);
                }
                return list;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        #endregion

        #region Metodos para Habitaciones

        public int agregarHabitacion(int numero, string capacidad, string cat, List<int> lstcom, char estado)
        {
            try
            {
                Habitacion Hab = new Habitacion();
                Hab.capacidad = capacidad;
                Hab.idCategoria = (from c in bd.Categoria
                                   where c.nombre.Equals(cat)
                                   select c).Single().idCategoria;
                Hab.estado = estado;
                Hab.numero = numero;
                bd.Habitacion.InsertOnSubmit(Hab);
                foreach (int idcom in lstcom)
                {
                    HabitacionComodidad hc = new HabitacionComodidad();
                    hc.idComodidad = idcom;
                    hc.idHabitacion = Hab.numero;
                    bd.HabitacionComodidad.InsertOnSubmit(hc);
                }
                bd.SubmitChanges();

                return Hab.numero;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public void modificarHabitacion(int numero, string capacidad, int idcat, List<int> lstcom, char estado)
        {
            try
            {
                Habitacion hab = (from h in bd.Habitacion
                                  where h.numero == numero
                                  select h).Single();
                hab.capacidad = capacidad;
                hab.idCategoria = idcat;
                hab.estado = estado;
                // Borramos las comodidades de la habitacion para cargarlas de nuevo
                //bd.ExecuteCommand("DELETE FROM HabitacionComodidad where idHabitacion=" + numero);
                var query = (from hcom in bd.HabitacionComodidad
                             where hcom.idHabitacion == numero
                             select hcom);
                IEnumerator<HabitacionComodidad> ienum = query.GetEnumerator();
                while(ienum.MoveNext())
                    bd.HabitacionComodidad.DeleteOnSubmit(ienum.Current);
                foreach (int idcom in lstcom)
                {
                    HabitacionComodidad hc = new HabitacionComodidad();
                    hc.idComodidad = idcom;
                    hc.idHabitacion = hab.numero;
                    bd.HabitacionComodidad.InsertOnSubmit(hc);
                }
                bd.SubmitChanges();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            
        }

        public List<string[]> obtenerHabitaciones(bool soloactivos)
        {
            try
            {
                IQueryable habitaciones;
                List<string[]> list = new List<string[]>();
                if (soloactivos)
                {
                    habitaciones = from h in bd.Habitacion
                                   where h.estado == 'S'
                                   select h;
                }
                else
                {
                    habitaciones = from h in bd.Habitacion
                                   select h;
                }

                foreach (Habitacion hab in habitaciones)
                {
                    string[] datos = new string[4];
                    datos[0] = hab.numero.ToString();
                    datos[1] = hab.capacidad;
                    datos[2] = hab.idCategoria.ToString();
                    datos[3] = hab.estado.ToString();
                    list.Add(datos);
                }
                return list;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        // No hay baja, solo se cambia el estado

        #endregion

        #region Metodos para HabitacionComodidad

        // JG: Cuando se usa esto???!!
        public bool AgregarHabCom(int numero, int idcom)
        {
            bool ok = true;
            try
            {
                var query = (from hc in bd.HabitacionComodidad
                             where hc.idHabitacion == numero && hc.idComodidad == idcom
                             select hc).Single();
            }
            catch (Exception)
            {
                ok = false;
            }
            if (!ok)
            {
                HabitacionComodidad hc = new HabitacionComodidad();
                hc.idComodidad = idcom;
                hc.idHabitacion = numero;
                bd.HabitacionComodidad.InsertOnSubmit(hc);
                bd.SubmitChanges();
                return true;
            }
            return false;
        }

        // Modificar tiene sentido ????, si los dos atributos son clave
        // JG: Cuando se usa esto???!!
        public void EliminarHabitacionComodidad(int numero, int idcom)
        {
            bool ok = true;
            try
            {
                var query = (from hc in bd.HabitacionComodidad
                             where hc.idComodidad == idcom && hc.idHabitacion == numero
                             select hc).Single();
            }
            catch (Exception)
            {
                ok = false;
            }
            if (!ok)
            {
                HabitacionComodidad habcom = (from hc in bd.HabitacionComodidad
                                              where hc.idHabitacion == numero && hc.idComodidad == idcom
                                              select hc).Single();
                bd.HabitacionComodidad.DeleteOnSubmit(habcom);
                bd.SubmitChanges();
            }
        }

        public List<string[]> obtenerComodidadesHabitacion(int numero)
        {
            try
            {
                var query = from hc in bd.HabitacionComodidad
                             where hc.idHabitacion == numero
                             select hc.idComodidad;
            
                List<string[]> list = new List<string[]>();
                foreach (int comod in query)
                {
                    Comodidad habcom = (from hc in bd.Comodidad
                                              where hc.idComodidad == comod
                                              select hc).Single();
                    string[] str = new string[4];
                    str[0]= habcom.idComodidad.ToString();
                    str[1]= habcom.nombre;
                    str[2]= habcom.descripcion;
                    str[3]= habcom.costoExtra.ToString();
                    list.Add(str);
                }
                return list;
                
                
            }catch(Exception e)
            {
                throw e;
            }
        }


        #endregion

        #region Metodos para Reserva

        public List<string[]> DarHabitacionesDisponibles(string ini, string fin, List<int> listcomodidades, int idcat, string cap)
        {
            List<string[]> list = new List<string[]>();
            string consulta = "select hab.numero from HotelORT.dbo.Habitacion hab where hab.estado = 'S' ";
            // Si paso como parametro la categoria
            if (idcat > 0)
            {
                consulta = consulta + " and hab.idCategoria = " + idcat;
            }
            // Si paso como parametro la capacidad
            if (cap != null)
            {
                consulta = consulta + " and hab.capacidad = '" + cap + "'";
            }
            string consreserva = "select hab.numero from HotelORT.dbo.Habitacion hab, HotelORT.dbo.Reserva r where hab.estado = 'S' ";
            consreserva = consreserva + " and '" + ini + "' <= r.checkIn and r.checkOut <= '" + fin + "' and hab.numero = r.numeroHab";

            // Chequeo que cumpla con las comodidades pedidas
            string conscom;
            if (listcomodidades.Count > 0)
            {
                string lista = "";
                int i =0;
                foreach(int j in listcomodidades) {
                    if(i ==(listcomodidades.Count - 1)) {
                        lista = lista + j.ToString();
                    }
                    else
                    {
                        lista = lista + j.ToString() + ",";
                    }
                    i++;
                }

                conscom = "select hab.numero from HotelORT.dbo.Habitacion hab where hab.estado = 'S' ";
                conscom = conscom + " and hab.idcategoria not in ( " + lista + ")";
            }
            else
            {
                conscom = "select hab.numero from HotelORT.dbo.Habitacion hab where hab.estado = 'S' and hab.estado = 'N'";
            }

            string consfinal = consulta + " except " + consreserva + " except " + conscom;
            IEnumerable<Habitacion> query = bd.ExecuteQuery<Habitacion>(consfinal);

            try
            {
                foreach (Habitacion hab in query)
                {
                    string[] datos = new string[1];
                    datos[0] = hab.numero.ToString();
                    list.Add(datos);
                }
            }
            catch (Exception e)
            {
                throw e;   
            }
            return list;
        }

        public List<string[]> obtenerReservas()
        {
            try
            {
                List<string[]> resultado = new List<string[]>();
                var reservas = (from r in bd.Reserva
                               select r).AsQueryable();
                int cant = reservas.Count();  
                IEnumerator<Reserva> ienum = reservas.GetEnumerator();
                string[] res;
                while (ienum.MoveNext())
                {
                    res = new string[6];

                    res[0] = ienum.Current.idReserva.ToString();
                    res[1] = ienum.Current.checkIn.ToString();
                    res[2] = ienum.Current.checkOut.ToString();
                    res[3] = ienum.Current.estado;
                    res[4] = ienum.Current.idCliente.ToString();
                    res[5] = ienum.Current.numeroHab.ToString();
                    resultado.Add(res);
                }
                return resultado;
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }

        public int realizarReserva(int idCliente, int numeroHab, DateTime fchin, DateTime fchout)
        {
            Reserva r = new Reserva();
            r.numeroHab = numeroHab;
            r.idCliente = idCliente;
            r.checkIn = fchin;
            r.checkOut = fchout;
            r.estado = "Reservado";
            bd.Reserva.InsertOnSubmit(r);
            bd.SubmitChanges();
            return r.idReserva;
        }

        public bool existeReserva(int idReserva)
        {
            bool ok = false;
            int resp = 0;
            string consulta = "select count(*) from HotelORT.dbo.Reserva r where r.idReserva = " + idReserva;
            IEnumerable<int> query = bd.ExecuteQuery<int>(consulta);
            foreach (int i in query)
            {
                resp = i + 1;
            }
            if (resp > 0) 
            {
                ok = true;
            }
            return ok;
        }

        public bool realizarCheckIn(int idReserva)
        {
            string consulta = "select * from HotelORT.dbo.Reserva r where r.idReserva = " + idReserva;
            IEnumerable<Reserva> query = bd.ExecuteQuery<Reserva>(consulta);
            foreach (Reserva r in query)
            {
                r.estado = "Ingresado";
            }
            bd.SubmitChanges();
            return true;
        }

        public bool realizarCheckOut(int idReserva, DateTime fecha)
        {
            bool ok = true;
            try
            {
                var query = (from res in bd.Reserva
                             where res.idReserva == idReserva
                             select res).Single();
            }
            catch (Exception)
            {
                ok = false;
            }
            if (!ok)
            {
                Reserva r = (from res in bd.Reserva
                             where res.idReserva == idReserva
                             select res).Single();
                r.estado = "Egresado";

                // Llamo a la factura
                bd.SubmitChanges();
                return true;
            }
            return false;
        }
        
        public void realizarCheckOut(int h)
        {
            Reserva res = (from r in bd.Reserva
                           where ((r.numeroHab == h) && (r.estado == "Ingresado"))
                           select r).Single();
            
            res.estado = "Egresado";
            bd.SubmitChanges();
        }

        public int calcularCantidadDeNoches(int hab)
        {
            Reserva r = (from res in bd.Reserva
                         where ((res.numeroHab == hab) && (res.estado == "Ingresado"))
                         select res).Single();

            int dias = (r.checkOut - r.checkIn).Days;
            return dias;
        }

        public double costoHabitacion(int hab)
        {
            Habitacion h1 = (from h in bd.Habitacion
                             where h.numero == hab
                              select h).Single();
            double costo = (from ch in bd.CostoHabitacion
                         where ((ch.Capacidad == h1.capacidad) && (ch.idCategoria == h1.idCategoria))
                         select ch).Single().Costo;
            return costo;
        }

        #endregion

        #region Metodos para Logs

        public void agregarLog(DateTime fecha, int idusuario, string accion, string clasificacion)
        {
            Log l = new Log();
            l.idUsuario = idusuario;
            l.fecha = fecha;
            l.accion = accion;
            l.clasificacion = clasificacion;
            bd.Log.InsertOnSubmit(l);
            bd.SubmitChanges();
        }

        public List<string[]> DarLogsFecha(DateTime Fecha)
        {
            List<string[]> list = new List<string[]>();
            var query = from l in bd.Log
                        where l.fecha.Day == Fecha.Day && l.fecha.Month == Fecha.Month && l.fecha.Year == Fecha.Year
                        select l;

            foreach (Log logs in query)
            {
                string[] datos = new string[3];
                datos[0] = logs.idUsuario.ToString();
                datos[1] = logs.accion;
                datos[2] = logs.clasificacion;
                list.Add(datos);
            }
            return list;
        }

        #endregion

        #region Metodos para Usuario

        public void validarUsuario(string usu, string key)
        {
            try
            {
                var q = (from u in bd.Usuario
                         where u.usunom == usu && u.password == key
                         select u).Single();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public int altaUsuario(string usuario, string password, string nombre, string apellido, DateTime nacimiento, char estado)
        {
            try
            {

                Datos.Usuario user = new Datos.Usuario();
                user.usunom = usuario;
                user.password = password;
                user.nombre = nombre;
                user.apellido = apellido;
                user.estado = estado;
                user.f_nacimiento = nacimiento;
                bd.Usuario.InsertOnSubmit(user);
                bd.SubmitChanges();
                return user.idUsuario;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void modificarUsuario(int idUsuario, string usuario, string password, string nombre, string apellido, DateTime nacimiento, char estado)
        {
            
            try
            {
                Usuario user = (from c in bd.Usuario
                                where c.idUsuario == idUsuario
                                select c).Single();
                user.usunom = usuario;
                user.password = password;
                user.nombre = nombre;
                user.apellido = apellido;
                user.estado = estado;
                user.f_nacimiento = nacimiento;
                bd.SubmitChanges();
            }
            catch (Exception e)
            {
                throw e;
            }
            
        }

        public void cambiarPasswordUsuario(int iduser, string pass)
        {
            try
            {
                Usuario user = (from c in bd.Usuario
                                where c.idUsuario == iduser
                                select c).Single();                
                user.password = pass;                
                bd.SubmitChanges();
            }
            catch (Exception e)
            {
                throw e;
            }

        }

        //public int traeUsuario(string usu)
        //{
        //    try
        //    {
        //        Usuario user = (from c in bd.Usuario
        //                        where c.usunom == usu
        //                        select c).Single();
        //        return user.idUsuario;
        //    }
        //    catch (Exception e)
        //    {
        //        throw e;
        //    }
        //}

        public List<string[]> obtenerUsuarios()
        {
            List<string[]> list = new List<string[]>();
            var query = from c in bd.Usuario
                        select c;

            foreach (Usuario usu in query)
            {
                string[] datos = new string[8];
                datos[0] = usu.idUsuario.ToString();
                datos[1] = usu.nombre;
                datos[2] = usu.apellido;
                datos[3] = usu.usunom;
                datos[4] = usu.password;
                datos[5] = usu.f_nacimiento.ToString();
                datos[6] = usu.estado.ToString();
                list.Add(datos);
            }
            return list;
        }

        #endregion

        #region Metodos para CostoHabitacion

        public void AgregarCostoHabitacion(int idcat, string cap, float precio)
        {
            try
            {
                var costHab = (from h in bd.CostoHabitacion
                               where h.idCategoria==idcat && h.Capacidad == cap
                             select h).AsQueryable();
                int cant = costHab.Count();
                CostoHabitacion costohab = new CostoHabitacion();
                costohab.Capacidad = cap;
                costohab.idCategoria = idcat;
                costohab.Costo = precio; 
                if (cant == 0)
                    bd.CostoHabitacion.InsertOnSubmit(costohab);                
                bd.SubmitChanges();
            }
            catch (InvalidOperationException dk)
            {
                CostoHabitacion hab = new CostoHabitacion();
                hab.idCategoria = idcat;
                hab.Capacidad = cap;
                hab.Costo = precio;
                bd.CostoHabitacion.InsertOnSubmit(hab);
                bd.SubmitChanges();
                throw dk;
            }
            
        }

        public float traerCostoHabitacion(int idcat, string cap)
        {
            try
            {
                var query = (from c in bd.CostoHabitacion
                             where c.Capacidad == cap && c.idCategoria == idcat
                             select c).Single();
                return (float)query.Costo;
            }
            catch (InvalidOperationException)
            {
                return 0;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        #endregion

        #region Metodos para Extras

        public List<String> traerExtras()
        {
            List<String> lista = new List<string>();
            var extras = (from e in bd.Extra
                          select e);
            foreach (Extra e in extras)
            {
                lista.Add(e.Nombre);    
            }
            return lista;
        }
        
        #endregion Extras

        public String traerClienteHabitacion(int habitacionActual)
        {
            String nombreCliente = (from r in bd.Reserva
                                    where r.estado == "Ingresado" && r.numeroHab == habitacionActual
                                    //&& r.checkOut == null
                                    select r).Single().Cliente.nombre;
            return nombreCliente;
        }

        public List<string> obtenerHabitacionesOcupadas()
        {
            try
            {
                List<string> list = new List<string>();
                var reservas = from r in bd.Reserva
                               where r.estado == "Ingresado"
                               select r;

                foreach (Reserva res in reservas)
                {
                    list.Add(res.numeroHab.ToString());
                }
                return list;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #region Metodos para Roles

        public int altaRol(string nombre, char estado)
        {
            try
            {
                Datos.Rol rol = new Datos.Rol();
                rol.nombre = nombre;
                rol.activo = estado;
                bd.Rol.InsertOnSubmit(rol);
                bd.SubmitChanges();
                return rol.idRol;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void bajaRol(int id)
        {
            bool ok = true;
            try
            {
                var query = (from r in bd.Rol
                             where r.idRol == id
                             select r).Single();
            }
            catch (Exception)
            {
                ok = true;
            }
            if (!ok)
            {
                Rol rol = (from r in bd.Rol
                           where r.idRol == id
                           select r).Single();
                bd.Rol.DeleteOnSubmit(rol);
                bd.SubmitChanges();
            }
        }

        public void updateRol(int id, string nombre, char estado)
        {
            try
            {
                Rol rol = (from r in bd.Rol
                           where r.idRol == id
                           select r).Single();
                rol.nombre = nombre;
                rol.activo = estado;
                bd.SubmitChanges();
            }
            catch (Exception es)
            {
                throw es;
            }
        }

        public List<string[]> traerRoles()
        {
            try
            {
                IQueryable query;
                List<string[]> list = new List<string[]>();
                query = from r in bd.Rol select r;
                foreach (Rol ro in query)
                {
                    string[] datos = new string[3];
                    datos[0] = ro.idRol.ToString();
                    datos[1] = ro.nombre;
                    datos[2] = ro.activo.ToString();
                    list.Add(datos);
                }
                return list;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        #endregion

        #region Metodos para Permisos

        public int altaPermiso(string desc)
        {
            try
            {
                Datos.Permiso per = new Datos.Permiso();
                per.PerDesc = desc;
                bd.Permiso.InsertOnSubmit(per);
                bd.SubmitChanges();
                return per.PerId;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void bajaPermiso(int id)
        {
            bool ok = false;
            try
            {
                var query = (from p in bd.Permiso
                             where p.PerId == id
                             select p).Single();
            }
            catch (Exception)
            {
                ok = true;
            }
            if (!ok)
            {
                Permiso per = (from p in bd.Permiso
                           where p.PerId == id
                           select p).Single();
                bd.Permiso.DeleteOnSubmit(per);
                bd.SubmitChanges();
            }
        }

        public void updatePermiso(int id, string desc)
        {
            bool ok = false;
            try
            {
                var query = (from p in bd.Permiso
                             where p.PerId == id
                             select p).Single();
            }
            catch (Exception)
            {
                ok = true;
            }
            if (!ok)
            {
                Permiso per = (from p in bd.Permiso
                           where p.PerId == id
                           select p).Single();
                per.PerDesc = desc;
                bd.SubmitChanges();
            }
        }

        public List<string[]> traerPermisos()
        {
            try
            {
                IQueryable query;
                List<string[]> list = new List<string[]>();
                query = from p in bd.Permiso select p;
                foreach (Permiso per in query)
                {
                    string[] datos = new string[2];
                    datos[0] = per.PerId.ToString();
                    datos[1] = per.PerDesc;
                    list.Add(datos);
                }
                return list;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public string traerPermiso(int id)
        {
            Permiso per = (from p in bd.Permiso
                           where p.PerId == id
                           select p).Single();
            return per.PerDesc;
        }

        #endregion

        #region Metodos para UsuarioRol

        public int altaUsuarioRol(int usuario, int rol)
        {
            try
            {
                Datos.UsuarioRol usurol = new Datos.UsuarioRol();
                usurol.idRol = rol;
                usurol.idUsuario = usuario;
                bd.UsuarioRol.InsertOnSubmit(usurol);
                bd.SubmitChanges();
                return 1;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void bajaUsuarioRol(int usuario, int rol)
        {
            try
            {
                UsuarioRol usurol = (from ur in bd.UsuarioRol
                                     where ur.idUsuario == usuario && ur.idRol == rol
                                     select ur).Single();
                bd.UsuarioRol.DeleteOnSubmit(usurol);
                bd.SubmitChanges();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public List<string[]> traeRolesUsuario(int usuario)
        {
            List<string[]> lista = new List<string[]>();

            string consulta = "select r.* from HotelORT.dbo.Rol r, HotelORT.dbo.UsuarioRol ur where ur.IdUsuario = " + usuario + " and ur.idRol = r.idRol";
            IEnumerable<Rol> query = bd.ExecuteQuery<Rol>(consulta);
            foreach (Rol rol in query)
            {
                string[] datos = new string[2];
                datos[0] = rol.idRol.ToString();
                datos[1] = rol.nombre;
                datos[2] = rol.activo.ToString();
                lista.Add(datos);
            }
            return lista;
        }

        public List<string[]> traeNoRolesUsuarios(int usuario)
        {
            List<string[]> lista = new List<string[]>();
            string consulta = "select * from HotelORT.dbo.Rol except select r.* from HotelORT.dbo.Rol r, HotelORT.dbo.UsuarioRol ur where ur.IdUsuario = " + usuario + " and ur.idRol = r.idRol";
            IEnumerable<Rol> query = bd.ExecuteQuery<Rol>(consulta);
            foreach (Rol rol in query)
            {
                string[] datos = new string[2];
                datos[0] = rol.idRol.ToString();
                datos[1] = rol.nombre;
                datos[2] = rol.activo.ToString();
                lista.Add(datos);
            }
            return lista;
        }

        #endregion

        #region Metodos para RolPermisos

        public int altaRolPermiso(int rol, int permiso)
        {
            try
            {
                Datos.RolPermiso rolper = new Datos.RolPermiso();
                rolper.idRol = rol;
                rolper.PerId = permiso;
                bd.RolPermiso.InsertOnSubmit(rolper);
                bd.SubmitChanges();
                return 1;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void bajaRolPermiso(int rol, int permiso)
        {
            try
            {
                RolPermiso rolper = (from pr in bd.RolPermiso
                                     where pr.PerId == permiso && pr.idRol == rol
                                     select pr).Single();
                bd.RolPermiso.DeleteOnSubmit(rolper);
                bd.SubmitChanges();
            }
            catch (Exception ex)
            {
                throw ex;   
            }
        }

        public List<string[]> traerPermisosRol(int rol)
        {
            List<string[]> lista = new List<string[]>();
            string consulta = "select p.* from HotelORT.dbo.Permiso p, HotelORT.dbo.RolPermiso pr where pr.idRol = " + rol + " and pr.PerId = p.PerId";
            IEnumerable<Permiso> query = bd.ExecuteQuery<Permiso>(consulta);
            foreach (Permiso perrol in query)
            {
                string[] datos = new string[2];
                datos[0] = perrol.PerId.ToString();
                datos[1] = perrol.PerDesc;
                lista.Add(datos);
            }
            return lista;
        }

        public List<string[]> traerNoPermisosRol(int rol)
        {
            List<string[]> lista = new List<string[]>();
            string consulta = "select * from HotelORT.dbo.Permiso except select p.* from HotelORT.dbo.Permiso p, HotelORT.dbo.RolPermiso pr where pr.idRol = " + rol + " and pr.PerId = p.PerId";
            IEnumerable<Permiso> query = bd.ExecuteQuery<Permiso>(consulta);
            foreach (Permiso perrol in query)
            {
                string[] datos = new string[2];
                datos[0] = perrol.PerId.ToString();
                datos[1] = perrol.PerDesc;
                lista.Add(datos);
            }
            return lista;
        }

        public List<string[]> traerPermisosUsuario(int usuario)
        {
            List<string[]> lstroles = new List<string[]>();
            List<string[]> lstPermisos = new List<string[]>();
            lstroles = traeRolesUsuario(usuario);
            foreach (string[] st in lstroles)
            {
                List<string[]> st2 = traerPermisosRol(int.Parse(st[0]));
                foreach(string[] str in st2) {
                    lstPermisos.Add(str);
                }
            }
            return lstPermisos;
        }

        #endregion


        #region Metodos de Pais
        public int altaPais(string nombrePais, char estado)
        {
            try
            {
                Pais pais = new Pais();
                pais.nombrePais = nombrePais;
                pais.activo = estado;
                bd.Pais.InsertOnSubmit(pais);
                bd.SubmitChanges();
                return pais.idPais;
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }

        public void modificarPais(int idPais, string nombrePais, char estado)
        {
            try
            {
                Pais pais = (from p in bd.Pais
                             where p.idPais == idPais
                             select p).Single();
                pais.nombrePais = nombrePais;
                pais.activo = estado;
                bd.SubmitChanges();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public List<string[]> obtenerPaises(bool soloactivos)
        {
            try
            {
                List<string[]> paises = new List<string[]>();
                IQueryable query;
                if (soloactivos)
                {
                    query = from c in bd.Pais
                                where c.activo == 'S' 
                                select c;
                }
                else
                {
                    query = from c in bd.Pais
                                select c;
                }

                foreach (Pais p in query)
                {
                    string[] datos = new string[3];
                    datos[0] = p.idPais.ToString();
                    datos[1] = p.nombrePais.ToString();
                    datos[2] = p.activo.ToString();
                    paises.Add(datos);
                }
                return paises;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public List<string[]> obtenerImpuestosPais(int idPais, bool soloactivos)
        {
            try
            {
                List<string[]> impuestos = new List<string[]>();
                IQueryable query;
                if (soloactivos)
                {
                    query = from imp in bd.Impuestos
                            where imp.activo == 'S' && imp.idPais == idPais
                            orderby imp.orden ascending
                            select imp;
                }
                else
                {
                    query = from imp in bd.Impuestos
                            where imp.idPais == idPais
                            orderby imp.orden ascending
                            select imp;
                }

                foreach (Impuestos impuesto in query)
                {
                    string[] datos = new string[5];
                    datos[0] = impuesto.idImpuesto.ToString();
                    datos[1] = impuesto.impuesto.ToString();
                    datos[2] = impuesto.valor.ToString();
                    datos[3] = impuesto.orden.ToString();
                    datos[4] = impuesto.activo.ToString();
                    impuestos.Add(datos);
                }
                return impuestos;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion


        public int altaImpuesto(int idPais, string impuesto, float valor, int orden, char estado)
        {
            try
            {
                Impuestos imp = new Impuestos();
                imp.idPais = idPais;
                imp.impuesto = impuesto;
                imp.valor = valor;
                imp.orden = orden;
                imp.activo = estado;
                bd.Impuestos.InsertOnSubmit(imp);
                bd.SubmitChanges();
                return imp.idImpuesto;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public void setOrdenImpuesto(int idImpuesto, int orden)
        {
            try
            {
                Impuestos imp = (from i in bd.Impuestos
                               where i.idImpuesto == idImpuesto
                               select i).Single();
                imp.orden = orden;
                bd.SubmitChanges();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public int obtenerIdPaisConfigurado()
        {
            try
            {
                //int idp = 0;
                int idp = (from conf in bd.Configuracion
                           select conf).Single().idPais;
                return idp;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void guardarConfiguracion(string nombreHotel,int idPais)
        {
            try
            {
                
                Configuracion conf;
                //bd.Connection.
                var conf2 = (from c in bd.Configuracion
                             select c).AsQueryable();
                int cant = conf2.Count();
                conf = new Configuracion();
                conf.idPais = idPais;
                conf.nombreHotel = nombreHotel;
                if (cant == 0)
                {
                    // No existe ninguna configuracion. Insertamos.
                    bd.Configuracion.InsertOnSubmit(conf);
                }
                bd.SubmitChanges();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public string[] obtenerConfiguracion()
        {
            try
            {
                string[] res;
                var conf2 = (from c in bd.Configuracion
                             select c).AsQueryable();
                int cant = conf2.Count();
                Configuracion conf = conf2.Single<Configuracion>();
                if (cant != 0)
                {
                    res = new string[2];

                    res[0] = conf.nombreHotel;
                    res[1] = conf.idPais.ToString();
                    return res;
                }
                else
                    throw new Exception("No existe una configuración del sistema.");
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    } 
}
